﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

using Size = System.Drawing.Size;

namespace Google.Maps.StaticMaps
{
    public class StaticMapService
    {
        public StaticMapService()
        {
            this.BaseUri = new Uri("http://maps.google.com/maps/api");
        }
        public StaticMapService(bool useHttps)
        {
            this.BaseUri = new Uri("https://maps.google.com/maps/api");
        }
        public StaticMapService(Uri baseUri)
        {
            this.BaseUri = baseUri;
        }

        public Uri BaseUri { get;set; }

        /// <summary>
        /// Retrieves a map and returns back the image bytes
        /// </summary>
        /// <param name="request"></param>
        /// <returns>byte array of the image bytes</returns>
        public byte[] GetImageBytes(StaticMapRequest mapOptions)
        {
            MemoryStream outputStream = new MemoryStream();

            GetMapToStream(mapOptions, outputStream);

             return outputStream.ToArray();
        }

        /// <summary>
        /// Retrieves the map with the given request and writes the image bytes to the given target stream.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="targetStream"></param>
        /// <returns>number of bytes written to the target stream</returns>
        public int GetMapToStream(StaticMapRequest mapOptions, System.IO.Stream outputStream)
        {
            Uri requestUri = new Uri(BaseUri, mapOptions.ToUri());

            int totalBytes=0;

            WebRequest request = WebRequest.Create(requestUri);
            using(WebResponse response = request.GetResponse())
            {
                Stream inputStream = response.GetResponseStream();

                int bytesRead=0;
                const int BYTE_BUFFER_LENGTH=4096;
                byte[] buffer = new byte[BYTE_BUFFER_LENGTH];

                do {
                    bytesRead = inputStream.Read(buffer, 0, BYTE_BUFFER_LENGTH);
                    outputStream.Write(buffer,0,bytesRead);
                    totalBytes += bytesRead;
                }
                while(bytesRead>BYTE_BUFFER_LENGTH);
            }

            return totalBytes;
        }

        /// <summary>
        /// Retrieves a static map image at a default size of 512x512 with the given parameters.
        /// </summary>
        /// <param name="center"></param>
        /// <param name="zoom"></param>
        /// <param name="sensor"></param>
        /// <returns></returns>
        public byte[] GetMap(Location center, int zoom, bool sensor)
        {
            StaticMapRequest request = new StaticMapRequest()
            {
                Center = center,
                Zoom = zoom,
                Sensor = sensor
            };

            return GetImageBytes(request);
        }

        /// <summary>
        /// Retrieves a static map image at a default size of 512x512 and using the specified image format.
        /// </summary>
        /// <param name="center">A location to center the map on</param>
        /// <param name="zoom">Zoom level to use</param>
        /// <param name="sensor">Pass true if the location was provided via a sensor</param>
        /// <param name="imageFormat">The format of the image</param>
        /// <returns></returns>
        public byte[] GetMap(Location center, int zoom, GMapsImageFormats imageFormat, bool sensor)
        {
            StaticMapRequest request = new StaticMapRequest()
            {
                Format = imageFormat,
                Center = center,
                Zoom = zoom,
                Sensor = sensor
            };

            return GetImageBytes(request);
        }

        /// <summary>
        /// Retrieves a static map image at a default size of 512x512 and using the specified image format.
        /// </summary>
        /// <param name="center">A location to center the map on</param>
        /// <param name="zoom">Zoom level to use</param>
        /// <param name="sensor">Pass true if the location was provided via a sensor</param>
        /// <param name="imageFormat">The format of the image</param>
        /// <returns></returns>
        public byte[] GetMap(Location center, int zoom, Size size, GMapsImageFormats imageFormat, bool sensor)
        {
            StaticMapRequest request = new StaticMapRequest()
            {
                Format = imageFormat,
                Size = size,
                Center = center,
                Zoom = zoom,
                Sensor = sensor
            };

            return GetImageBytes(request);
        }


        public byte[] GetMapWithCenterMarked(Location center, int zoom, bool sensor)
        {
            StaticMapRequest request = new StaticMapRequest()
            {
                Center = center,
                Zoom = zoom,
                Sensor = sensor
            };
            request.Markers.Add(request.Center);

            return GetImageBytes(request);
        }


    }
}
